#ifndef _CALLBACK_H_
#define _CALLBACK_H_

#include <stdlib.h>
#include <new>

#pragma once

class ObjectMethodBase
{
public:
    virtual ~ObjectMethodBase() throw() {}
    virtual int32_t execute( int32_t code, void * data ) = 0;
};

template< class T >
class ObjectMethod : public ObjectMethodBase
{
public:
    typedef int32_t (T::*pFunc)( int32_t code, void * data );

    ObjectMethod( T * obj, pFunc pfunc )
        : m_obj( obj ), m_pfunc( pfunc )
    {}

    virtual ~ObjectMethod() throw() {}

    int32_t execute( int32_t code, void * data )
    {
        return (m_obj->*m_pfunc)( code, data );
    }

private:
    T *     m_obj;
    pFunc   m_pfunc;
};

class CallbackObject
{
public:
    CallbackObject()
        : m_objmethod( NULL )
    {}

    virtual ~CallbackObject() throw()
    {
        if( m_objmethod )
            m_objmethod->~ObjectMethodBase();
    }

    int32_t handle_event( int32_t code, void * data )
    {
        return m_objmethod->execute( code, data );
    }

    template<class T>
    void set_handler( T * obj, typename ObjectMethod<T>::pFunc method )
    {
        m_objmethod = new((void*)m_storage)ObjectMethod<T>( obj, method );
    }

private:
    char m_storage[sizeof(ObjectMethod<ObjectMethodBase>)];
    ObjectMethodBase * m_objmethod;
};

#endif //_CALLBACK_H_

